#include <iostream>
#include <vector>
#include <pthread.h>
#include<semaphore.h>
using namespace std;

template <class T>
class RingQueue
{
    static const u_int32_t defaultcapa=10;
public:
    RingQueue(int c=defaultcapa):_p_step(0),_c_step(0),_capa(c)
    {
        _q.resize(_capa);
        pthread_mutex_init(&_pmutex,nullptr);
        pthread_mutex_init(&_cmutex,nullptr);
        sem_init(&_space_sem,0,_capa);
        sem_init(&_datum_sem,0,0);
    }
    void Push(const T&in)
    {
        sem_wait(&_space_sem);//申请使用空间，队列中剩余空间减少

        pthread_mutex_lock(&_pmutex);//加锁，防止出现线程安全问题
        _q[_p_step++]=in;//生产数据

        _p_step%=(_capa);//绕着跑

        pthread_mutex_unlock(&_pmutex);//解锁

        sem_post(&_datum_sem);//队列中数据个数增加   
    }
    void Pop(T&out)
    {
        sem_wait(&_datum_sem);//申请使用数据，队列中剩余数据减少

        pthread_mutex_lock(&_cmutex);//加锁，防止出现线程安全问题
        out=_q[_c_step++];//消费数据

        _c_step%=(_capa);//绕着跑

        pthread_mutex_unlock(&_cmutex);//解锁

        sem_post(&_space_sem);//队列中剩余空间个数增加
    }
    ~RingQueue()
    {
        sem_destroy(&_space_sem);
        sem_destroy(&_datum_sem);
        pthread_mutex_destroy(&_pmutex);
        pthread_mutex_destroy(&_cmutex);
    }
private:
    vector<T> _q;//环形队列
    u_int32_t _p_step; // 生产者使用的下标
    u_int32_t _c_step; // 消费者使用的下标
    u_int32_t _capa;   // 环形队列的最大容量
    sem_t _space_sem;//空间信号量，记路环形队列中剩余空间的个数
    sem_t _datum_sem;//资源信号量，记路环形队列中数据的个数
    pthread_mutex_t _pmutex;//生产者锁
    pthread_mutex_t _cmutex;//消费者锁
};